home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
dfue
/
elcheapofax
/
trace
/
rcs
/
trace.c,v
< prev
Wrap
Text File
|
1995-03-09
|
8KB
|
369 lines
head 1.2;
access;
symbols
OCT93:1.2;
locks;
comment @ * @;
1.2
date 93.07.10.03.26.42; author Rhialto; state Exp;
branches;
next 1.1;
1.1
date 93.07.01.00.48.49; author Rhialto; state Exp;
branches;
next ;
desc
@Trace activity of the serial.device. Usefull to spy on other
fax programs.
@
1.2
log
@Also trace SDCMD_SETPARAMS.
@
text
@;/*
dcc -proto trace.c -o trace
quit
*/
/*
* Serial Port tracing utility. Uses one or two dirty tricks, but mostly
* plays by the book. There are style problems with AbortIO, though.
* Perhaps you'd best redirect output to some FAST disk.
*
* $Id: trace.c,v 1.1 1993/07/01 00:48:49 Rhialto Exp $
* $Log: trace.c,v $
* Revision 1.1 1993/07/01 00:48:49 Rhialto
* Initial revision
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <devices/serial.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
extern struct ExecBase *SysBase;
struct MsgPort *ReplyPort;
struct MsgPort *BeginIOPort;
void (*OldBeginIO)(__A1 struct IOExtSer *ios, __A6 struct Device *dev);
void (*OldAbortIO)(__A1 struct IOExtSer *ios, __A6 struct Device *dev);
int Outstanding;
struct MyIO {
struct IOExtSer io;
struct IOExtSer *orig;
struct Task *SigTask;
};
void
logit(struct IOExtSer *ios)
{
#define BFSIZ 160
char buffer[BFSIZ];
char *p, *q;
int len;
switch (ios->IOSer.io_Command) {
case CMD_WRITE:
q = "CMD_WRITE";
len = ios->IOSer.io_Length;
break;
case CMD_READ:
q = "CMD_READ ";
len = ios->IOSer.io_Actual;
if (ios->IOSer.io_Error) {
printf("CMD_READ : error %d\n", ios->IOSer.io_Error);
return;
}
break;
case SDCMD_QUERY:
printf("SDCMD_QUERY: %d\n", ios->IOSer.io_Actual);
return;
case SDCMD_SETPARAMS:
printf("SDCMD_SETPARAMS: CtlChar: %08lx, RBufLen: %d, Baud: %d,\n",
ios->io_CtlChar,
ios->io_RBufLen,
ios->io_Baud);
printf("\tTermArray: %08lx %08lx, ReadLen: %d, WriteLen: %d, StopBits: %d,\n",
ios->io_TermArray.TermArray0,
ios->io_TermArray.TermArray1,
ios->io_ReadLen,
ios->io_WriteLen,
ios->io_StopBits);
printf("\tXDISABLED %d EOFMODE %d SHARED %d RAD_BOOGIE %d 7WIRE %d\n",
(ios->io_SerFlags & SERF_XDISABLED) != 0,
(ios->io_SerFlags & SERF_EOFMODE) != 0,
(ios->io_SerFlags & SERF_SHARED) != 0,
(ios->io_SerFlags & SERF_RAD_BOOGIE) != 0,
(ios->io_SerFlags & SERF_7WIRE) != 0);
printf("\tPARTY_ODD %d PARTY_ON %d MSPON %d MARK %d\n",
(ios->io_SerFlags & SERF_PARTY_ODD) != 0,
(ios->io_SerFlags & SERF_PARTY_ON) != 0,
(ios->io_ExtFlags & SEXTF_MSPON) != 0,
(ios->io_ExtFlags & SEXTF_MARK) != 0);
return;
default:
printf("CMD_%d\n", ios->IOSer.io_Command);
return;
}
sprintf(buffer, "%s %3d: ", q, len);
p = buffer + strlen(buffer);
q = ios->IOSer.io_Data;
while (len-- > 0 && p < &buffer[BFSIZ-5]) {
unsigned char c;
c = *q++;
if (c & 0x80) {
*p++ = '~';
c &= 0x7F;
}
if (c < 0x20 || c == 0x7F) {
*p++ = '^';
c ^= 0x40;
}
*p++ = c;
}
*p++ = '\n';
*p = '\0';
fputs(buffer,stdout);
}
/*
* Here is where the I/O starts. We trace in the following way:
*
* CMD_WRITE: trace immediately, by putting it on the main process
* port. It will be OldBeginIO()ed after tracing.
*
* CMD_READ: wait with trace until we know what we read. Patch up the
* ProcPort so that WE will get it back when complete.
* The main process will ReplyMsg() it after tracing.
*/
__geta4
void
MyBeginIO(__A1 struct IOExtSer *ios, __A6 struct Device *dev)
{
switch (ios->IOSer.io_Command) {
case CMD_READ:
case SDCMD_QUERY:
{
struct MyIO *myio;
int quick;
quick = ios->IOSer.io_Flags & IOF_QUICK;
myio = AllocMem(sizeof(*myio), MEMF_ANY);
if (myio == NULL) {
/* Sorry, no memory to trace this one */
goto untraced;
}
myio->io = *ios;
myio->io.IOSer.io_Flags &= ~IOF_QUICK;
myio->io.IOSer.io_Message.mn_ReplyPort = ReplyPort;
myio->orig = ios;
ios->IOSer.io_Message.mn_Node.ln_Succ = (void *)myio;
ios->IOSer.io_Message.mn_Node.ln_Type = NT_FREEMSG;
myio->SigTask = FindTask(NULL);
Outstanding++;
(*OldBeginIO)(&myio->io, dev);
if (quick || ios->IOSer.io_Message.mn_ReplyPort == NULL) {
/* Argh! It seems that many programs (well, at least
* VLT) take liberties with setting the ReplyPort when
* they're doing a QUERY, or a quick READ. Admittedly,
* quick I/O is guaranteed, under limited circumstances,
* but that's no reason not to have a reply port...
* Anyway, we'll have to Wait() here, wether he likes
* it or not...
*/
Wait(1);
}
}
break;
case CMD_WRITE:
case SDCMD_SETPARAMS:
ios->IOSer.io_Flags &= ~IOF_QUICK;
PutMsg(BeginIOPort, &ios->IOSer.io_Message);
break;
default:
untraced:
(*OldBeginIO)(ios, dev);
}
}
/*
* Grmpf. This is ugly. The NT_FREEMSG means that it is safe to
* assume the ln_Succ points to our copied request. Forbid() is
* needed to make sure it won't get invalid before we us it.
*/
__geta4
void
MyAbortIO(__A1 struct IOExtSer *ios, __A6 struct Device *dev)
{
Forbid();
if (ios->IOSer.io_Message.mn_Node.ln_Type == NT_FREEMSG) {
(*OldAbortIO)((void *)ios->IOSer.io_Message.mn_Node.ln_Succ, dev);
Permit();
} else {
Permit();
(*OldAbortIO)(ios, dev);
}
}
void
HandlePorts(void)
{
struct IOExtSer *ios;
while (ios = GetMsg(ReplyPort)) {
struct MyIO *myio;
/* Prevent AbortIO() of my copied request */
ios->IOSer.io_Message.mn_Node.ln_Type = NT_REPLYMSG;
if (Outstanding > 1 || Outstanding < 0) {
printf("[%d] ", Outstanding);
}
logit(ios);
Outstanding--;
myio = ios;
ios = myio->orig;
ios->IOSer.io_Error = myio->io.IOSer.io_Error;
ios->IOSer.io_Actual = myio->io.IOSer.io_Actual;
ios->io_Status = myio->io.io_Status;
if (!(ios->IOSer.io_Flags & IOF_QUICK) &&
ios->IOSer.io_Message.mn_ReplyPort) {
ReplyMsg(&ios->IOSer.io_Message);
} else {
Signal(myio->SigTask, 1);
}
FreeMem(myio, sizeof(*myio));
}
while (ios = GetMsg(BeginIOPort)) {
logit(ios);
(*OldBeginIO)(ios, ios->IOSer.io_Device);
}
}
int
main(int argc, char **argv)
{
char *serialname;
int unit;
struct IOExtSer *ios;
struct Device *dev;
int running;
long waitmask;
if (argc < 3) {
printf("Usage: [run] trace serial.device 0\n");
exit(10);
}
serialname = argv[1];
unit = atoi(argv[2]);
printf("Tracing %s %d\n", serialname, unit);
ReplyPort = CreatePort("trace ReplyPort", -1);
if (ReplyPort == NULL)
goto exit;
BeginIOPort = CreatePort("trace BeginIOPort", -1);
if (BeginIOPort == NULL)
goto exit;
ios = (struct IOExtSer *)CreateExtIO(ReplyPort, sizeof(*ios));
if (ios == NULL)
goto exit;
if (OpenDevice(serialname, unit, (struct IORequest *)ios, 0)) {
Forbid();
dev = FindName(&SysBase->DeviceList, serialname);
Permit();
if (dev == NULL) {
printf("Can't find %s...\n", serialname);
goto exit;
}
} else {
dev = ios->IOSer.io_Device;
CloseDevice((struct IORequest *)ios);
}
signal(SIGINT, SIG_IGN);
OldBeginIO = SetFunction(dev, DEV_BEGINIO, MyBeginIO);
OldAbortIO = SetFunction(dev, DEV_ABORTIO, MyAbortIO);
running = 1;
waitmask = SIGBREAKF_CTRL_F | 1L << ReplyPort->mp_SigBit
| 1L << BeginIOPort->mp_SigBit;
while (running || Outstanding > 0) {
long mask;
mask = Wait(waitmask);
HandlePorts();
if (mask & SIGBREAKF_CTRL_F) {
SetFunction(dev, DEV_BEGINIO, OldBeginIO);
running = 0;
}
}
SetFunction(dev, DEV_BEGINIO, OldBeginIO);
Delay(10);
SetFunction(dev, DEV_ABORTIO, OldAbortIO);
HandlePorts();
Delay(10);
HandlePorts();
printf("Done tracing %s %d\n", serialname, unit);
exit:
if (ios)
DeleteExtIO((struct IORequest *)ios);
if (ReplyPort)
DeletePort(ReplyPort);
if (BeginIOPort)
DeletePort(BeginIOPort);
return 0;
}
@
1.1
log
@Initial revision
@
text
@d11 5
a15 2
* $Id$
* $Log$
d21 1
d60 4
d68 23
d169 1
d181 1
a181 1
* assume the ln_Succ points to our copied request. Forbod() is
d277 2
@